Skip to content

feat: recommend_bucketed_config() -- discrete regime-bucketed adaptive recommendation - #125

Merged
jc-macdonald merged 1 commit into
mainfrom
feat/123-regime-bucketed-adaptive
Aug 20, 2026
Merged

feat: recommend_bucketed_config() -- discrete regime-bucketed adaptive recommendation#125
jc-macdonald merged 1 commit into
mainfrom
feat/123-regime-bucketed-adaptive

Conversation

@jc-macdonald

Copy link
Copy Markdown
Collaborator

Summary

Closes #123.

RegimeSurrogate interpolates continuously across regime descriptors, but needs reasonably dense training coverage -- RF surrogates (its default backend) extrapolate poorly (effectively flat) outside their training range. There was no equivalent for the sparse case: a handful of named regimes, each far from the others and far from any existing training data, where the actual need is "find a good config for each one directly, then aggregate into named buckets."

Why this matters

Found deriving VBPCA hyperparameter buckets for extreme-aspect-ratio data shapes (yoavram-lab/VBPCApy#116) -- genomics-scale (p >> n) and ecological/survey-scale (n >> p) regimes, 2-3 per extreme. The pattern that actually worked was hand-rolled in analysis/trade_study/option_a_aspect_ratio.py: run_adaptive per regime, pick the best trial, group into named buckets, aggregate. This formalizes that as a reusable trade-study function.

Changes

recommend_bucketed_config(regimes, bucket_fn, world_factory, scorer, factors, observables, *, primary, n_trials=30, n_reps=1, seed=42):

  • Runs run_adaptive independently per regime (world_factory(regime) builds a regime-scoped Simulator)
  • Selects each regime's single best trial by the primary observable, respecting its Direction (minimize/maximize)
  • Groups regimes into named buckets via bucket_fn(name, regime) -> bucket_name
  • Aggregates each bucket's per-regime best configs: median for continuous/discrete factors, mode (most common) for categorical

Uses run_adaptive's n_reps (#122, already merged) to avoid the single-draw fragility that motivated #122 in the first place.

Test plan

  • just ci passes, regime.py at 100% coverage
  • New tests: median aggregation across regimes with different optima, buckets stay separate when bucket_fn doesn't merge them, categorical aggregation picks the mode, Direction.MAXIMIZE is respected, rejects empty regimes/unknown primary

🤖 Generated with Claude Code

…e recommendation (#123)

RegimeSurrogate interpolates continuously across regime descriptors,
but needs reasonably dense training coverage -- RF surrogates
extrapolate poorly (effectively flat) outside their training range.
There was no equivalent for the sparse case: a handful of named
regimes, each far from the others and far from any existing training
data, where you just want "find a good config for each one directly,
then aggregate into named buckets."

Found deriving VBPCA hyperparameter buckets for extreme-aspect-ratio
data shapes (yoavram-lab/VBPCApy#116) -- the pattern that actually
worked (run_adaptive per regime + median aggregation into buckets) was
hand-rolled there; this formalizes it as a reusable trade-study
function.

recommend_bucketed_config() runs run_adaptive per regime (respecting
n_reps, #122), selects each regime's best trial by a primary
observable (respecting its Direction), groups regimes via a
caller-supplied bucket_fn, and aggregates each bucket's per-regime best
configs -- median for continuous/discrete factors, mode for
categorical.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jc-macdonald
jc-macdonald merged commit 1edbb08 into main Aug 20, 2026
4 checks passed
@jc-macdonald
jc-macdonald deleted the feat/123-regime-bucketed-adaptive branch August 20, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No discrete regime-bucketed adaptive-recommendation helper (complement to RegimeSurrogate for sparse regime sets)

1 participant